package clien;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.IOException;
import java.nio.charset.Charset;

public class RestClient {

    private static final Charset UTF_8 = Charset.forName("utf-8");

    private String serverUrl;
    private String httpMethod;
    private String clientData;
    private int connectTimeout;
    private int socketTimeout;

    public RestClient(String url, String method, String data) {
        this.serverUrl = url;
        this.httpMethod = method;
        this.clientData = data;
        this.connectTimeout = -1;
        this.socketTimeout = -1;
    }

    public RestClient(String url) {
        this.serverUrl = url;
        this.httpMethod = "GET";
        this.clientData = null;
        this.connectTimeout = -1;
        this.socketTimeout = -1;
    }

    public RestClient(String url, String data) {
        this.serverUrl = url;
        this.httpMethod = "GET";
        this.clientData = data;
        this.connectTimeout = -1;
        this.socketTimeout = -1;
    }

    public void setURL(String url) {
        this.serverUrl = url;
    }

    public void setMethod(String method) {
        this.httpMethod = method;
    }

    public void setData(String data) {
        this.clientData = data;
    }

    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    public void setSocketTimeout(int socketTimeout) {
        this.socketTimeout = socketTimeout;
    }

    public String execute() throws RestException {
        if (null == this.serverUrl) {
            return null;
        }

        String ret = this.httpExecute();

        return ret;
    }

    private DefaultHttpClient getHttpClient() {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        httpClient.getParams().setParameter("http.protocol.content-charset", "utf-8");
        if (0 < this.connectTimeout) {
            httpClient.getParams().setParameter("http.connection.timeout", this.connectTimeout * 1000);
        }

        if (0 < this.socketTimeout) {
            httpClient.getParams().setParameter("http.socket.timeout", this.socketTimeout * 1000);
        }

        return httpClient;
    }

    private String getURLWithData() {
        if (this.clientData != null) {
            return this.serverUrl.endsWith("?") ? this.serverUrl + this.clientData : this.serverUrl + "?" + this.clientData;
        } else {
            return this.serverUrl;
        }
    }

    private String httpExecute() throws RestException {
        String ret = null;
        DefaultHttpClient httpclient = this.getHttpClient();

        try {
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            if (this.httpMethod.equalsIgnoreCase(RestMethod.GET)) {
                HttpGet req = new HttpGet(this.getURLWithData());
                req.setHeader("Content-Type", "application/json;charset=UTF-8");
                ret = httpclient.execute(req, responseHandler);
            } else if (this.httpMethod.equalsIgnoreCase(RestMethod.POST)) {
                HttpPost req = new HttpPost(this.serverUrl);
                req.setHeader("Content-Type", "application/json;charset=UTF-8");
                if (null != this.clientData) {
                    req.setEntity(new StringEntity(this.clientData, UTF_8));
                }
                ret = httpclient.execute(req, responseHandler);
            } else if (this.httpMethod.equalsIgnoreCase(RestMethod.PUT)) {
                HttpPut req = new HttpPut(this.serverUrl);
                req.setHeader("Content-Type", "application/json;charset=UTF-8");
                if (null != this.clientData) {
                    req.setEntity(new StringEntity(this.clientData, UTF_8));
                }
                ret = httpclient.execute(req, responseHandler);
            } else if (this.httpMethod.equalsIgnoreCase(RestMethod.DELETE)) {
                HttpDelete req = new HttpDelete(this.getURLWithData());
                req.setHeader("Content-Type", "application/json;charset=UTF-8");
                ret = httpclient.execute(req, responseHandler);
            }
        } catch (ClientProtocolException cpe) {
            throw new RestException(cpe.getMessage(), cpe.getCause());
        } catch (IOException ioe) {
            throw new RestException(ioe.getMessage(), ioe.getCause());
        } catch (Exception e) {
            throw new RestException(e.getMessage(), e.getCause());
        } finally {
            httpclient.getConnectionManager().shutdown();
        }

        return ret;
    }
}